{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Joint Measurements Kata\n",
    "\n",
    "**Joint Measurements** quantum kata is a series of exercises designed to get you familiar with programming in Q#. It covers the joint parity measurements and using them for distinguishing quantum states or for performing multi-qubit gates.\n",
    "\n",
    "* In Q# joint measurements are implemented as the [Measure](https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.intrinsic.measure) operation.\n",
    "* You can read more about measurements of multi-qubit Pauli operators in the [Q# documentation](https://docs.microsoft.com/quantum/concepts/pauli-measurements).\n",
    "\n",
    "Each task is wrapped in one operation preceded by the description of the task.  Your goal is to fill in the blank (marked with `// ...` comments)\n",
    "with some Q# code that solves the task. To verify your answer, run the cell using Ctrl/⌘+Enter.\n",
    "\n",
    "The tasks are given in approximate order of increasing difficulty; harder ones are marked with asterisks."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To begin, first prepare this notebook for execution (if you skip this step, you'll get \"Syntax does not match any known patterns\" error when you try to execute Q# code in the next cells):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%package Microsoft.Quantum.Katas::0.10.1911.1607"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> The package versions in the output of the cell above should always match. If you are running the Notebooks locally and the versions do not match, please install the IQ# version that matches the version of the `Microsoft.Quantum.Katas` package.\n",
    "> <details>\n",
    "> <summary><u>How to install the right IQ# version</u></summary>\n",
    "> For example, if the version of `Microsoft.Quantum.Katas` package above is 0.1.2.3, the installation steps are as follows:\n",
    ">\n",
    "> 1. Stop the kernel.\n",
    "> 2. Uninstall the existing version of IQ#:\n",
    ">        dotnet tool uninstall microsoft.quantum.iqsharp -g\n",
    "> 3. Install the matching version:\n",
    ">        dotnet tool install microsoft.quantum.iqsharp -g --version 0.1.2.3\n",
    "> 4. Reinstall the kernel:\n",
    ">        dotnet iqsharp install\n",
    "> 5. Restart the Notebook.\n",
    "> </details>\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%workspace reload"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 1. Single-qubit measurement\n",
    "\n",
    "**Input:** Two qubits (stored in an array) which are guaranteed to be either in superposition of states $|00\\rangle$ and $|11\\rangle$ or in superposition of states $|01\\rangle$ and $|10\\rangle$.\n",
    "\n",
    "**Output:**  0 if qubits were in the first superposition, 1 if they were in the second superposition.  \n",
    "*The state of the qubits at the end of the operation does not matter.*\n",
    "\n",
    "<br/>\n",
    "<details closed>\n",
    "  <summary>Need a hint? Click here </summary>\n",
    "    Use two single-qubit measurements. \n",
    "</details>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%kata T01_SingleQubitMeasurement_Test \n",
    "\n",
    "operation SingleQubitMeasurement (qs : Qubit[]) : Int {\n",
    "    // ...\n",
    "    return -1;\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 2. Parity measurement\n",
    "\n",
    "**Inputs**: Two qubits (stored in an array) which are guaranteed to be either in superposition of states $|00\\rangle$ and $|11\\rangle$ or in superposition of states $|01\\rangle$ and $|10\\rangle$.\n",
    "\n",
    "**Output**: 0 if qubits were in the first superposition, 1 if they were in the second superposition.  \n",
    "*The state of the qubits at the end of the operation should be the same as the starting state.*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%kata T02_ParityMeasurement_Test \n",
    "\n",
    "operation ParityMeasurement (qs : Qubit[]) : Int {\n",
    "    // ...\n",
    "    return -1;\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 3. $|0000\\rangle + |1111\\rangle$ or $|0011\\rangle + |1100\\rangle$  ?\n",
    "**Inputs**: Four qubits (stored in an array) which are guaranteed to be either in superposition of states $|0000\\rangle$ and $|1111\\rangle$ or in superposition of states $|0011\\rangle$ and $|1100\\rangle$.\n",
    "\n",
    "**Output** : 0 if qubits were in the first superposition, 1 if they were in the second superposition.  \n",
    "*The state of the qubits at the end of the operation should be the same as the starting state.*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%kata T03_GHZOrGHZWithX_Test \n",
    "\n",
    "operation GHZOrGHZWithX (qs : Qubit[]) : Int {\n",
    "    // ...\n",
    "    return -1;\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 4. $|0..0\\rangle + |1..1\\rangle$ or W state ?\n",
    "\n",
    "**Inputs:** An even number of qubits (stored in an array) which are guaranteed to be either in a superposition of states |0..0$\\rangle$ and |1..1$\\rangle$ or in the [W state](https://en.wikipedia.org/wiki/W_state).\n",
    "\n",
    "**Output:** 0 if qubits were in the first superposition, 1 if they were in the second superposition. \n",
    "*The state of the qubits at the end of the operation should be the same as the starting state.*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%kata T04_GHZOrWState_Test\n",
    "\n",
    "operation GHZOrWState (qs : Qubit[]) : Int {\n",
    "    // ...\n",
    "    return -1;\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 5*. Parity measurement in different basis\n",
    "\n",
    "**Inputs:** Two qubits (stored in an array) which are guaranteed to be\n",
    "* either in superposition $\\alpha |00\\rangle + \\beta |01\\rangle + \\beta |10\\rangle + \\alpha |11\\rangle$\n",
    "* or in superposition $\\alpha |00\\rangle - \\beta |01\\rangle + \\beta |10\\rangle - \\alpha |11\\rangle$\n",
    "\n",
    "**Output:** 0 if qubits were in the first superposition, 1 if they were in the second superposition.  \n",
    "*The state of the qubits at the end of the operation should be the same as the starting state.*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%kata T05_DifferentBasis_Test\n",
    "\n",
    "operation DifferentBasis (qs : Qubit[]) : Int {\n",
    "    // ...\n",
    "    return -1;\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 6*. Controlled X gate with $|0\\rangle$ target\n",
    "\n",
    "**Input:** Two unentangled qubits (stored in an array of length 2). The first qubit (`qs[0]`) will be in state $|\\psi\\rangle = \\alpha |0\\rangle + \\beta |1\\rangle$ , the second (`qs[1]`) - in state $|0\\rangle$ (this can be written as two-qubit state $\\big(\\alpha |0\\rangle + \\beta |1\\rangle\\big) \\otimes |0\\rangle$). \n",
    "\n",
    "**Output:** Change the two-qubit state to $\\alpha |00\\rangle + \\beta |11\\rangle$ using only single-qubit gates and joint measurements. Do not use two-qubit gates. You do not need to allocate extra qubits."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%kata T06_ControlledX_Test\n",
    "\n",
    "operation ControlledX (qs : Qubit[]) : Unit {\n",
    "    // ...\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 7**. Controlled X gate with arbitrary target\n",
    "\n",
    "**Input:** Two qubits (stored in an array of length 2) in an arbitrary two-qubit state $\\alpha |00\\rangle + \\beta |01\\rangle + \\color{blue}\\gamma |10\\rangle  + \\color{blue}\\delta |11\\rangle$.\n",
    "\n",
    "**Goal:** Change the two-qubit state to $\\alpha |00\\rangle + \\beta |01\\rangle + \\color{red}\\delta |10\\rangle  + \\color{red}\\gamma |11\\rangle$ using only single-qubit gates and joint measurements.  Do not use two-qubit gates.\n",
    "\n",
    "> A general-case implementation of CNOT gate via joint measurements is described in [this paper](https://arxiv.org/pdf/1201.5734.pdf).\n",
    "\n",
    "<details>\n",
    "  <summary>Need a hint? Click here</summary>\n",
    "  You can use an extra qubit to perform this operation.\n",
    "</details>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%kata T07_ControlledX_General_Test\n",
    "\n",
    "operation ControlledX_General (qs : Qubit[]) : Unit {\n",
    "    // ...\n",
    "}"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Q#",
   "language": "qsharp",
   "name": "iqsharp"
  },
  "language_info": {
   "file_extension": ".qs",
   "mimetype": "text/x-qsharp",
   "name": "qsharp",
   "version": "0.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
